package com.file.parser.socialsecurity;


import com.file.bo.ResponseData;
import com.file.bo.socialsecurity.ShanghaiIndividualRecordSheet;
import com.file.bo.socialsecurity.ShanghaiIndividualRecordSheet1;
import com.file.bo.socialsecurity.ShanghaiInsuranceParticipation;
import com.file.constant.ErrorCode;
import com.file.parser.BasePdfParser;
import com.file.util.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
import technology.tabula.*;
import technology.tabula.detectors.SpreadsheetDetectionAlgorithm;
import technology.tabula.extractors.SpreadsheetExtractionAlgorithm;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
public class ShanghaiSocialSecurityPdfParser extends BasePdfParser {

    public ResponseData<String> parseShanghaiSocialSecurityPdfToJson(String daId, String filePath) {
        log.info("parseShanghaiSocialSecurityPdfToJson started, daId:{}", daId);
        String json = null;

        try {
            if (filePath.contains("cbzm")) {
                ShanghaiInsuranceParticipation shanghaiInsuranceParticipation = parseShanghaiInsuranceParticipation(filePath);
                json = JsonUtils.convertObjectToJson(shanghaiInsuranceParticipation);
            } else if (filePath.contains("qyd")) {//NOSONAR
                Object shanghaiIndividualRecordSheet = parseShanghaiIndividualRecordSheet(filePath);
                json = JsonUtils.convertObjectToJson(shanghaiIndividualRecordSheet);//NOSONAR
            } else {
                log.error("OnError|{}||{}|{}|{}|{}", ErrorCode.FILE_PARSE_EXCEPTION.getCode(), daId, "", "", "parseShanghaiSocialSecurityPdfToJson failed, new type not supported");
                return new ResponseData<>(null, ErrorCode.FILE_PARSE_EXCEPTION.getCode(), ErrorCode.FILE_PARSE_EXCEPTION.getMsg());
            }
        } catch (Exception e) {
            log.error("OnError|{}||{}|{}|{}|{}", ErrorCode.FILE_PARSE_EXCEPTION.getCode(), daId, "", "", "parseShanghaiSocialSecurityPdfToJson failed", e);
            return new ResponseData<>(null, ErrorCode.FILE_PARSE_EXCEPTION.getCode(), ErrorCode.FILE_PARSE_EXCEPTION.getMsg());
        }

        log.info("parseShanghaiSocialSecurityPdfToJson completed, daId:{}", daId);
        return new ResponseData<>(json, ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg());
    }

    private ShanghaiInsuranceParticipation parseShanghaiInsuranceParticipation(String filePath) {
        ShanghaiInsuranceParticipation shanghaiInsuranceParticipation = parseShanghaiInsuranceParticipationHeader(filePath);
        List<List<String>> rowList = parseFileToRowList(filePath);
//        for (List<String> cellList : rowList) {
//            System.out.println(cellList);
//        }

        parseListToBO(rowList, shanghaiInsuranceParticipation);
        return shanghaiInsuranceParticipation;
    }

    private ShanghaiInsuranceParticipation parseShanghaiInsuranceParticipationHeader(String filePath) {
        ShanghaiInsuranceParticipation shanghaiInsuranceParticipation = new ShanghaiInsuranceParticipation();
        String pdfText = getPdfTextByStripper(filePath)
                .replace(System.getProperty("line.separator", "\n"), StringUtils.EMPTY);

        String notes = pdfText.substring(pdfText.lastIndexOf("备注：") + 3, pdfText.lastIndexOf("上海市社会保险事业管理中心业务专用章")).replace("\u00A0", "").replace("u", "").trim();
        shanghaiInsuranceParticipation.setNotes(notes);

        String printMechanism = pdfText.substring(pdfText.lastIndexOf("经办机构：") + 5, pdfText.lastIndexOf("打印日期：")).trim();
        shanghaiInsuranceParticipation.setPrintMechanism(printMechanism);

        String printTime = pdfText.substring(pdfText.lastIndexOf("打印日期：") + 5, pdfText.lastIndexOf("电子印章验证码")).replace("\u00A0", "").trim();
        shanghaiInsuranceParticipation.setPrintTime(printTime);

        return shanghaiInsuranceParticipation;
    }

    private Object parseShanghaiIndividualRecordSheet(String filePath) { //NOSONAR
        String pdfText = getPdfTextByStripper2(filePath).replace(System.getProperty("line.separator", "\n"), "");
        if (pdfText.contains("参保人姓名")){
            ShanghaiIndividualRecordSheet  shanghaiIndividualRecordSheet = parseShanghaiIndividualRecordSheetHeader(filePath);
            List<List<String>> rowList = parseFileToRowList(filePath);
            parseListToBO(rowList, shanghaiIndividualRecordSheet);
            return shanghaiIndividualRecordSheet;
        }else{
            ShanghaiIndividualRecordSheet1  shanghaiIndividualRecordSheet = parseShanghaiIndividualRecordSheetHeaderNew(pdfText);
            List<List<String>> rowList = parseFileToRowList(filePath);
            parseListToBONew(rowList, shanghaiIndividualRecordSheet);
            return shanghaiIndividualRecordSheet;
        }

    }

    private void parseListToBO(List<List<String>> rowList, ShanghaiIndividualRecordSheet shanghaiIndividualRecordSheet) {
        String sectionName = "";

        List<ShanghaiIndividualRecordSheet.PaymentDetail> paymentDetailList = new ArrayList<>();
        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < rowList.size(); i++) {
            List<String> cellList = rowList.get(i);

            if (StringUtils.equals(cellList.get(0), "项目年份")) {
                sectionName = "项目年份";
                continue;
            } else if (StringUtils.equals(cellList.get(0), "补充资料")) {
                sectionName = "补充资料";
                continue;
            }

            switch (sectionName) {//NOSONAR
                case "项目年份":
                    ShanghaiIndividualRecordSheet.PaymentDetail paymentDetail = new ShanghaiIndividualRecordSheet.PaymentDetail();
                    paymentDetail.setProjectYear(cellList.get(0));
                    paymentDetail.setPaymentMonths(cellList.get(1));
                    paymentDetail.setPrincipalAndInterestTotalDepositAmount(cellList.get(2));
                    paymentDetail.setIndividualPaymentPrincipalAndInterest(cellList.get(3));
                    paymentDetail.setBookkeepingAmount(cellList.get(4));
                    paymentDetail.setIndividualPaymentAmount(cellList.get(5));
                    paymentDetail.setTheYearCalculateInterest(cellList.get(6));
                    paymentDetailList.add(paymentDetail);
                    break;
                case "补充资料":
                    sb.append(cellList.get(0));
                    break;

            }
        }

        shanghaiIndividualRecordSheet.setPaymentDetailList(paymentDetailList);
        shanghaiIndividualRecordSheet.setSupplementaryInformation(sb.toString());
    }

    private void parseListToBONew(List<List<String>> rowList, ShanghaiIndividualRecordSheet1 shanghaiIndividualRecordSheet) {


        List<ShanghaiIndividualRecordSheet1.AccountingRecord> accountingRecords = new ArrayList<>();

        for (int i = 0; i < rowList.size(); i++) {
            List<String> cellList = rowList.get(i);
            if (cellList.get(0).matches("\\d+")){
                ShanghaiIndividualRecordSheet1.AccountingRecord record=new ShanghaiIndividualRecordSheet1.AccountingRecord();
                record.setSerialNumber(cellList.get(0));
                record.setDate(cellList.get(1));
                record.setInsuredUnit(cellList.get(2));
                record.setAccountStatus(cellList.get(3));
                record.setAdjustmentYearMonth(cellList.get(4));
                accountingRecords.add( record);
            }
        }

        shanghaiIndividualRecordSheet.setAccountingRecord(accountingRecords);

    }

    private ShanghaiIndividualRecordSheet parseShanghaiIndividualRecordSheetHeader(String filePath) {
        ShanghaiIndividualRecordSheet shanghaiIndividualRecordSheet = new ShanghaiIndividualRecordSheet();
        String pdfText = getPdfTextByStripper2(filePath);
//        System.out.println(pdfText);

        String insuredName = pdfText.substring(pdfText.lastIndexOf("参保人姓名：") + 6, pdfText.lastIndexOf("个人账号")).replace("\u00A0", "").trim();
        shanghaiIndividualRecordSheet.setInsuredName(insuredName);

        String personalAccount = pdfText.substring(pdfText.lastIndexOf("个人账号（公民身份证号码）：") + 14, pdfText.lastIndexOf("参保单位名称：")).trim();
        shanghaiIndividualRecordSheet.setPersonalAccount(personalAccount);

        String insuredUnitName = pdfText.substring(pdfText.lastIndexOf("参保单位名称：") + 7, pdfText.lastIndexOf("连续工龄：") - 5).trim();
        shanghaiIndividualRecordSheet.setInsuredUnitName(insuredUnitName);

        String continuousWorkingYears = pdfText.substring(pdfText.lastIndexOf("连续工龄：") + 5, pdfText.lastIndexOf("养老保险个人账户的记账情况")).trim();
        shanghaiIndividualRecordSheet.setContinuousWorkingYears(continuousWorkingYears);

        String monetaryUnit = pdfText.substring(pdfText.lastIndexOf("金额单位：") + 5, pdfText.lastIndexOf("项目")).trim();
        shanghaiIndividualRecordSheet.setMonetaryUnit(monetaryUnit);

        String operatingAgency = pdfText.substring(pdfText.lastIndexOf("经办机构：") + 5, pdfText.lastIndexOf("经办机构：") + 18).trim();
        shanghaiIndividualRecordSheet.setOperatingAgency(operatingAgency);

        String printTime = pdfText.substring(pdfText.lastIndexOf("打印日期：") + 5, pdfText.lastIndexOf("打印日期：") + 14).trim();
        shanghaiIndividualRecordSheet.setPrintTime(printTime);

        return shanghaiIndividualRecordSheet;
    }

    private ShanghaiIndividualRecordSheet1 parseShanghaiIndividualRecordSheetHeaderNew(String pdfText) {
        ShanghaiIndividualRecordSheet1 shanghaiIndividualRecordSheet = new ShanghaiIndividualRecordSheet1();

        String insuredName = pdfText.substring(pdfText.lastIndexOf("姓 名：") + 4, pdfText.lastIndexOf("证件号码：")).trim();
        shanghaiIndividualRecordSheet.setName(insuredName);

        String idno = pdfText.substring(pdfText.lastIndexOf("证件号码：") + 5, pdfText.lastIndexOf("★养老保险个人账户")).trim();
        shanghaiIndividualRecordSheet.setIdNo(idno);

        String personalAccount = pdfText.substring(pdfText.lastIndexOf("养老保险个人账户") + 8, pdfText.lastIndexOf("上海市社会保险事业管理中心")).replace("\u00A0", "").trim();
        shanghaiIndividualRecordSheet.setPersonalAccount(personalAccount);



        return shanghaiIndividualRecordSheet;
    }


    private void parseListToBO(List<List<String>> rowList, ShanghaiInsuranceParticipation shanghaiInsuranceParticipation) {
        String sectionName = "";
        List<ShanghaiInsuranceParticipation.PaymentDetail> paymentDetailList1 = new ArrayList<>();
        List<ShanghaiInsuranceParticipation.PaymentDetail> paymentDetailList2 = new ArrayList<>();
        List<ShanghaiInsuranceParticipation.PaymentDetail> paymentDetailList3 = new ArrayList<>();
        List<ShanghaiInsuranceParticipation.PaymentUnitInformation> paymentUnitInformationList = new ArrayList<>();

        for (int i = 0; i < rowList.size(); i++) {
            List<String> cellList = rowList.get(i);

            if (StringUtils.equals(cellList.get(0), "姓名")) {
                sectionName = "姓名";
            } else if (StringUtils.equals(cellList.get(0), "序号")) {
                sectionName = "序号";
                continue;
            } else if (cellList.get(0).contains("个月缴费单位信息")) {
                continue;
            } else if (StringUtils.equals(cellList.get(0), "缴费单位名称")) {
                sectionName = "缴费单位名称";
                continue;
            } else if (cellList.get(0).contains("累计缴费月数")) {
                sectionName = "累计缴费月数";
            }

            switch (sectionName) {//NOSONAR
                case "姓名":
                    shanghaiInsuranceParticipation.setName(cellList.get(1));
                    shanghaiInsuranceParticipation.setSocialSecurityNumber(cellList.get(3));
                    shanghaiInsuranceParticipation.setIdNo(cellList.get(5));
                    break;
                case "序号":
                    if (StringUtils.isNotBlank(cellList.get(0))) {
                        ShanghaiInsuranceParticipation.PaymentDetail paymentDetail1 = new ShanghaiInsuranceParticipation.PaymentDetail();
                        paymentDetail1.setSerialNumber(cellList.get(0));
                        paymentDetail1.setDate(cellList.get(1));
                        paymentDetail1.setPaymentStatus(cellList.get(2));
                        paymentDetail1.setSupplementaryPaymentAndRefundDate(cellList.get(3));
                        paymentDetailList1.add(paymentDetail1);
                    }
                    if (StringUtils.isNotBlank(cellList.get(4))) {
                        ShanghaiInsuranceParticipation.PaymentDetail paymentDetail2 = new ShanghaiInsuranceParticipation.PaymentDetail();
                        paymentDetail2.setSerialNumber(cellList.get(4));
                        paymentDetail2.setDate(cellList.get(5));
                        paymentDetail2.setPaymentStatus(cellList.get(6));
                        paymentDetail2.setSupplementaryPaymentAndRefundDate(cellList.get(7));
                        paymentDetailList2.add(paymentDetail2);
                    }
                    if (StringUtils.isNotBlank(cellList.get(8))) {
                        ShanghaiInsuranceParticipation.PaymentDetail paymentDetail3 = new ShanghaiInsuranceParticipation.PaymentDetail();
                        paymentDetail3.setSerialNumber(cellList.get(8));
                        paymentDetail3.setDate(cellList.get(9));
                        paymentDetail3.setPaymentStatus(cellList.get(10));
                        paymentDetail3.setSupplementaryPaymentAndRefundDate(cellList.get(11));
                        paymentDetailList3.add(paymentDetail3);
                    }
                    break;
                case "缴费单位名称":
                    if (StringUtils.isNotBlank(cellList.get(0))) {
                        ShanghaiInsuranceParticipation.PaymentUnitInformation paymentUnitInformation1 = new ShanghaiInsuranceParticipation.PaymentUnitInformation();
                        paymentUnitInformation1.setPaymentUnitName(cellList.get(0));
                        paymentUnitInformation1.setPaymentStartAndEndTime(cellList.get(1));
                        paymentUnitInformationList.add(paymentUnitInformation1);
                    }
                    if (StringUtils.isNotBlank(cellList.get(2))) {
                        ShanghaiInsuranceParticipation.PaymentUnitInformation paymentUnitInformation2 = new ShanghaiInsuranceParticipation.PaymentUnitInformation();
                        paymentUnitInformation2.setPaymentUnitName(cellList.get(2));
                        paymentUnitInformation2.setPaymentStartAndEndTime(cellList.get(3));
                        paymentUnitInformationList.add(paymentUnitInformation2);
                    }
                    break;
                case "累计缴费月数":
                    shanghaiInsuranceParticipation.setAccumulatedPaymentMonths(cellList.get(1));
                    break;
            }
        }

        List<ShanghaiInsuranceParticipation.PaymentDetail> paymentDetailList = new ArrayList<>(paymentDetailList1);
        if (CollectionUtils.isNotEmpty(paymentDetailList2)) {
            paymentDetailList.addAll(paymentDetailList2);
        }
        if (CollectionUtils.isNotEmpty(paymentDetailList3)) {
            paymentDetailList.addAll(paymentDetailList3);
        }
        shanghaiInsuranceParticipation.setPaymentDetailList(paymentDetailList);
        shanghaiInsuranceParticipation.setPaymentUnitInformationList(paymentUnitInformationList);
    }

    private List<List<String>> parseFileToRowList(String filePath) {
        // 1. 读取文件
        File pdf = new File(filePath);

        //页面所有table的记录，每一个元素代表下面一条记录cellList
        List<List<String>> rowList = new ArrayList<>();

        // 2. pdfbox读取PDDocument
        try (PDDocument pdfDocument = PDDocument.load(pdf)) {
            // 3. tabula新建ObjectExtractor和NurminenDetectionAlgorithm，同时准备接收表格Rectangle的结构
            ObjectExtractor objectExtractor = new ObjectExtractor(pdfDocument);
            SpreadsheetDetectionAlgorithm detectionAlgorithm = new SpreadsheetDetectionAlgorithm();
            Map<Integer, List<Rectangle>> pageNumber2RectangleListMap = new HashMap<>();//key为页的序号， value为对应的Rectangle的list

            // 4. 获取每页的PageIterator
            PageIterator pageIterator = objectExtractor.extract();

            // 5. 解析每页的Rectangle
            // 如果单页pdf中有多个Rectangle，则解析出来的List<Rectangle>会有多个对象
            while (pageIterator.hasNext()) {
                Page page = pageIterator.next();
                List<Rectangle> rectangleList = detectionAlgorithm.detect(page);
                if (rectangleList.size() > 0) {
                    pageNumber2RectangleListMap.put(page.getPageNumber(), rectangleList);
                }
            }

            // 6.通过table位置获取表格具体内容
            SpreadsheetExtractionAlgorithm extractionAlgorithm = new SpreadsheetExtractionAlgorithm();

            // 如果单页pdf中有多个表格，则解析出来的List<Rectangle>会有多个对象
            for (Map.Entry<Integer, List<Rectangle>> entry : pageNumber2RectangleListMap.entrySet()) {
                Page page = objectExtractor.extract(entry.getKey());
                Rectangle rectangle = null;

                List<Rectangle> rectangleList = entry.getValue();
                for (Rectangle r : rectangleList) {
                    double rectangleHeight = r.getHeight();
                    if (Double.compare(rectangleHeight, 0) > 0) {
                        rectangle = r;
                        break;
                    }
                }
                if (rectangle == null) {
                    throw new RuntimeException("rectangle is null.");
                }

                if (entry.getKey() > 1) {
                    rectangle.setTop(rectangle.getTop());
                }
                rectangle.setBottom(rectangle.getBottom() + 300);
                Page area = page.getArea(rectangle);

                // 如果每页有多个表格，解析每一个table
                List<Table> tableList = extractionAlgorithm.extract(area);
                for (Table table : tableList) {
                    for (int i = 0; i < table.getRowCount(); i++) {
                        List<String> cellList = new ArrayList<>();//一条记录，每个单元格占一个元素
                        for (int j = 0; j < table.getColCount(); j++) {
                            cellList.add(table.getCell(i, j).getText(false));
                        }
                        rowList.add(cellList);
                    }
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }

        return rowList;
    }

    public static void main(String[] args) throws Exception {

        String filePath = "D:\\上海市2024年个人权益记录单20250627161906_qyd.pdf";
        new RemoveWaterMark().removeWaterMark(filePath);
        ShanghaiSocialSecurityPdfParser shanghaiSocialSecurityPdfParser = new ShanghaiSocialSecurityPdfParser();
        String json = shanghaiSocialSecurityPdfParser.parseShanghaiSocialSecurityPdfToJson("", filePath).getData();
        System.out.println(json);
    }

}
